#!/usr/bin/env python
from kivy.metrics import dp
from kivy.logger import Logger
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.uix.scrollview import ScrollView
from kivy.uix.switch import Switch
from kivy.uix.textinput import TextInput

from amgineirc.view.messageView import MessageView
from amgineirc.viewModel.settings.serversViewModel import ServersViewModel

__all__ = ['EditServerPopup', 'ServersView']

class EditServerPopup(Popup, MessageView):
    
    def __init__(self, command, domain, domain_used, port, secure, nick, password, validate_handler):
        self.key = domain
        self.command = command
        self.validate_handler = validate_handler
        layout = FloatLayout()
        Popup.__init__(self,
                       title=command + ' ' + self.key,
                       content=layout,
                       size_hint=(None, None),
                       size=(400, 500),
                       auto_dismiss=False)
        MessageView.__init__(self)
        # domain name
        label = self.buildFormLabel('Server Domain Name',
                                    'example: irc.ircstorm.net',
                                    size_hint=(0.5, 0.16),
                                    pos_hint={'x':0.0, 'y':0.8})
        if domain_used:
            self.domain_input = Label(text=domain,
                                      size_hint=(0.5, 0.16),
                                      pos_hint={'x':0.5, 'y':0.8})
        else:
            self.domain_input = TextInput(text=domain,
                                          multiline=False,
                                          size_hint=(0.5, 0.16),
                                          pos_hint={'x':0.5, 'y':0.8})
        layout.add_widget(label)
        layout.add_widget(self.domain_input)
        # domain port
        label = self.buildFormLabel('Server Port',
                                    'Often 6667 without TLS and often 6697 with TLS.',
                                    size_hint=(0.5, 0.16),
                                    pos_hint={'x':0.0, 'y':0.64})
        self.port_input = TextInput(text=str(port),
                                    multiline=False,
                                    size_hint=(0.5, 0.16),
                                    pos_hint={'x':0.5, 'y':0.64})
        layout.add_widget(label)
        layout.add_widget(self.port_input)
        # secure
        label = self.buildFormLabel('TLS',
                                    'A Protocol for a secure connection.',
                                    size_hint=(0.5, 0.16),
                                    pos_hint={'x':0.0, 'y':0.48})
        self.secure_switch = Switch(active=secure,
                                    size_hint=(0.5, 0.16),
                                    pos_hint={'x':0.5, 'y':0.48})
        layout.add_widget(label)
        layout.add_widget(self.secure_switch)
        # my nick
        label = self.buildFormLabel('My Nick',
                                    '',
                                    size_hint=(0.5, 0.16),
                                    pos_hint={'x':0.0, 'y':0.32})
        self.nick_input = TextInput(text=nick,
                                    multiline=False,
                                    size_hint=(0.5, 0.16),
                                    pos_hint={'x':0.5, 'y':0.32})
        layout.add_widget(label)
        layout.add_widget(self.nick_input)
        # my nick password
        label = self.buildFormLabel('My Nick Password',
                                    'For verifing my nick with NickServ',
                                    size_hint=(0.5, 0.16),
                                    pos_hint={'x':0.0, 'y':0.16})
        self.nick_password_input = TextInput(text=password,
                                        multiline=False,
                                        size_hint=(0.5, 0.16),
                                        pos_hint={'x':0.5, 'y':0.16})
        layout.add_widget(label)
        layout.add_widget(self.nick_password_input)
        # command button
        layout.add_widget(Button(text=ServersView.submit_command,
                                 size_hint=(0.5, 0.1),
                                 pos_hint={'x':0.0, 'y':0.0},
                                 on_press=self.validate_data))
        layout.add_widget(Button(text='Cancel',
                                 size_hint=(0.5, 0.1),
                                 pos_hint={'x':0.5, 'y':0.0},
                                 on_press=self.dismiss))
          

    def validate_data(self, instance):
        ok, msg = self.validate_handler(instance.text,
                                        self.key,
                                        self.domain_input.text.strip(),
                                        self.port_input.text.strip(),
                                        self.secure_switch.active,
                                        self.nick_input.text.strip(),
                                        self.nick_password_input.text.strip())
        if ok:
            self.dismiss()
        else:
            self.message_warn(msg)
                

class _ServerRecordButton(Button, MessageView):
    def __init__(self, domain, port, secure, nick, nick_password, vm_command_option_handler, **kargs):
        if 'text' in kargs:
            del(kargs['text'])
        kargs['markup'] = True
        kargs['on_press'] = self.w_handle_server_record_button_on_press
        kargs['size_hint'] = (1.0, None)
        kargs['height'] = dp(50)
        Button.__init__(self, **kargs)
        MessageView.__init__(self)
        self.reset_text(domain, port, secure, nick, nick_password)
        self.vm_command_option_handler = vm_command_option_handler
        
    def reset_text(self, domain, port, secure, nick, nick_password):
        self.domain = domain
        pwd = '*' * len(nick_password)
        sec = '+' if secure else '-'
        self.text = "[b]%s[/b] : %i %s [b]%s[/b] %s" % (domain, port, sec, nick, pwd)
        
    def w_handle_server_record_button_on_press(self, instance):
        self.select_options('Options for ' + self.domain,
                            ServersView.commands,
                            self.vm_command_option_handler,
                            self.domain)
            

class _ServersListView(ScrollView):
    def __init__(self, command_option_handler, **kargs):
        kargs['do_scroll_x'] = False
        ScrollView.__init__(self, **kargs)
        # view model command handling method
        self.command_option_handler = command_option_handler
        # create a default grid layout with custom width/height
        self._layout = GridLayout(cols=1,
                                  size_hint=(1.0, None))
        # when we add children to the grid layout, its size doesn't change at
        # all. we need to ensure that the height will be the minimum required to
        # contain all the childs. (otherwise, we'll child outside the bounding
        # box of the childs)
        self._layout.bind(minimum_height=self._layout.setter('height'))
        self.add_widget(self._layout)
        
    def log(self, domain, port, secure, nick, nick_password):
        w = _ServerRecordButton(domain, port, secure, nick, nick_password,
                                self.command_option_handler)
        y = self.scroll_y
        self._layout.add_widget(w)
        # if the scroll view was scrolled to the end
        # then stay at the end
        if y == 1.0:
            self.scroll_y = y
        return w


class ServersView(FloatLayout, MessageView):
    """a view for the domains page
        
        use bind_apply to bind the vm method to read and store the vars
        use bind_reset to bind the vm method to reset the vars

    """
    submit_command = 'Submit'
    create_command = 'Create A New Server Connection Record'
    delete_command = 'Delete'
    edit_command = 'Edit'
    
    commands = [edit_command, delete_command]

    page_intro = "This page is where you can create, edit and delete your IRC server connection records."\
                 " You can edit or delete a server connection record by touching it in the list."

    def __init__(self, appdata, **kargs):
        FloatLayout.__init__(self, **kargs)
        MessageView.__init__(self)
        self._appdata = appdata
        # page heading
        self.intro = Label(text=self.__class__.page_intro,
                      size_hint=(1.0, 0.4),
                      pos_hint={'x':0.0, 'y':0.6},
                      line_height=1.5)
        self.bind(width=self.on_width_handler)
        self.add_widget(self.intro)
        # list of current domains
        self.add_button = Button(text=self.__class__.create_command,
                                 size_hint=(1.0, 0.2),
                                 pos_hint={'x':0.0, 'y':0.4})
        self.add_button.bind(on_press=self.w_add_button_handler)
        self.list_view = _ServersListView(self.w_command_option_handler,
                                        size_hint=(1.0, 0.4),
                                        pos_hint={'x':0.0, 'y':0.0})
        self.add_widget(self.add_button)
        self.add_widget(self.list_view)
        self._domains = {}
        self.vm_option_command_handler = lambda **kargs : None
        # initialize the view model
        ServersViewModel(self, appdata)

    def on_width_handler(self, instance, value):
        if value > 40:
            value -= 20
        self.intro.text_size = (value-20, None)
 
    # widget methods
            
    def w_command_option_handler(self, command, key):
        # the user has selected a command for a server record
        # instance is a _ServerOptionButton
        if self.vm_option_command_handler is not None:
            self.vm_option_command_handler(command, key)
            
    def w_add_button_handler(self, instance):
        if self.vm_option_command_handler is not None:
            self.vm_option_command_handler(instance.text, '')
        
    # vm methods

    def vm_add_domain(self, domain, port, secure, nick, nick_password):
        if domain not in self._domains:
            self._domains[domain] = self.list_view.log(domain, port, secure, nick, nick_password)

    def vm_show_domain_added(self, domain, port, secure, nick, nick_password):
        self.vm_add_domain(domain, port, secure, nick, nick_password)
        # inform user of the added domain
        self.message_success('Added "%s"' % (domain))
        
    def vm_show_domain_edited(self, oldname, domain, port, secure, nick, nick_password):
        if oldname in self._domains:
            if oldname != domain:
                self._domains[domain] = self._domains[oldname]
                del(self._domains[oldname])
            self._domains[domain].reset_text(domain, port, secure, nick, nick_password)
            # inform user of the rename
            self.message_success('Modified "%s"' % (domain))

    def vm_show_domain_deleted(self, domain):
        if domain in self._domains:
            text = self._domains[domain].text
            self._domains[domain].parent.remove_widget(self._domains[domain])
            # self.list_view.remove_widget(self._domains[name])
            del(self._domains[domain])
            # inform user of the deleted domain
            self.message_success('Deleted "%s"' % (domain))
        
    def vm_bind_command(self, func):
        # func must accept **kargs
        # 'command', 'domain_name', 'new_name'
        self.vm_option_command_handler = func
